# -*- coding: UTF-8 -*-
from struct import unpack

# 读取并存储 bmp 文件
class ReadBMPFile:
    def __init__(self, filePath):
        file = open(filePath, "rb")
        # 读取 bmp 文件的文件头    14 字节
        self.bfType = unpack("<h", file.read(2))[0]  # 0x4d42 对应BM 表示这是Windows支持的位图格式
        self.bfSize = unpack("<i", file.read(4))[0]  # 位图文件大小
        self.bfReserved1 = unpack("<h", file.read(2))[0]  # 保留字段 必须设为 0
        self.bfReserved2 = unpack("<h", file.read(2))[0]  # 保留字段 必须设为 0
        self.bfOffBits = unpack("<i", file.read(4))[0]  # 偏移量 从文件头到位图数据需偏移多少字节（位图信息头、调色板长度等不是固定的，这时就需要这个参数了）
        # 读取 bmp 文件的位图信息头 40 字节
        self.biSize = unpack("<i", file.read(4))[0]  # 所需要的字节数
        self.biWidth = unpack("<i", file.read(4))[0]  # 图像的宽度 单位 像素
        self.biHeight = unpack("<i", file.read(4))[0]  # 图像的高度 单位 像素
        self.biPlanes = unpack("<h", file.read(2))[0]  # 说明颜色平面数 总设为 1
        self.biBitCount = unpack("<h", file.read(2))[0]  # 颜色位数

        self.biCompression = unpack("<i", file.read(4))[0]  # 图像压缩的数据类型
        self.biSizeImage = unpack("<i", file.read(4))[0]  # 图像大小
        self.biXPelsPerMeter = unpack("<i", file.read(4))[0]  # 水平分辨率
        self.biYPelsPerMeter = unpack("<i", file.read(4))[0]  # 垂直分辨率
        self.biClrUsed = unpack("<i", file.read(4))[0]  # 实际使用的彩色表中的颜色索引数
        self.biClrImportant = unpack("<i", file.read(4))[0]  # 对图像显示有重要影响的颜色索引的数目
        self.bmp_palette = []
        self.bmp_data = []
        #读调色板，读数据
        """if self.biBitCount != 24:
            print("输入的图片比特值为 ：" + str(self.biBitCount) + "\t 与程序不匹配")
        """
        #24位真彩，没有调色板
        if self.biBitCount == 24:
            for height in range(self.biHeight):
                #定义行
                bmp_data_row = []
                # 四字节填充位检测
                count = 0
                for width in range(self.biWidth):
                    #每一个元素为R，G，B值。各一个字节
                    bmp_data_row.append(
                        [unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0]])
                    #当前行字节数加三
                    count = count + 3
                # bmp 四字节对齐原则
                while count % 4 != 0:
                    file.read(1)
                    count = count + 1
                #添加这一行到数据区
                self.bmp_data.append(bmp_data_row)
        #格式错误
        elif self.biBitCount == 0:
            print("输入图片为jpeg格式")
        #
        else:
            #读取调色板，共2的bitcount种
            for row in range(2 ** self.biBitCount):
                #一个调色板为一个列表，有4个属性
                #R,G,B,保留值
                #[R,G,B,E]
                self.bmp_palette.append([unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0],unpack("<B", file.read(1))[0]])
            #读取数据区
            for height in range(self.biHeight):
                # 定义行
                bmp_data_row = []
                # 四字节填充位检测
                count = 0
                for width in range(self.biWidth):
                    # 每一个元素为R，G，B值。各一个字节
                    #[R,G,B]
                    bmp_data_row.append(
                        [unpack("<X", file.read(self.biBitCount))[0], unpack("<X", file.read(self.biBitCount))[0], unpack("<X", file.read(self.biBitCount))[0]])
                    # 当前行字节数加三
                    count = count + 3
                # bmp 四字节对齐原则
                while count % 4 != 0:
                    file.read(1)
                    count = count + 1
                # 添加这一行到数据区
                self.bmp_data.append(bmp_data_row)

        #反转，倒置变为正置
        self.bmp_data.reverse()
        file.close()
        # R, G, B 三个通道
        self.R = []
        self.G = []
        self.B = []

        for row in range(self.biHeight):
            R_row = []
            G_row = []
            B_row = []
            for col in range(self.biWidth):
                B_row.append(self.bmp_data[row][col][0])
                G_row.append(self.bmp_data[row][col][1])
                R_row.append(self.bmp_data[row][col][2])
            self.B.append(B_row)
            self.G.append(G_row)
            self.R.append(R_row)